﻿
package test {
	import extremefx.IEnumerator;
	import extremefx.collections.ArrayList;
	import extremefx.collections.Dictionary;
	import extremefx.collections.List;
	import extremefx.collections.TreeNode;
	import extremefx.tools.ObjectUtils;
	import extremefx.unitTest.Assert;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.text.TextField;
	import flash.text.TextFormat;		

	/**
	 * @author Marcelo Volmaro
	 */
	
	[Frame(factoryClass="extremefx.Preloader")];
	public final class CollectionsTest extends Sprite {

		private var _tf:TextField;
		
		public function main():void{
			var tf:TextField = _tf = new TextField();
			var tfmt:TextFormat = new TextFormat("arial unicode ms", 14, 0);
			stage.addEventListener(Event.RESIZE, resizeStage);
			addChild(tf);
			tf.x = 0;
			tf.y = 0;
			tf.width = stage.stageWidth;
			tf.height = stage.stageHeight;
			tf.defaultTextFormat = tfmt;
			Assert.setOutput(tf);
			
			testArrayList();
			testDictionary();
			testLinkedList();
			testTree();
		}

		private function testTree():void {
			
			var tree1:TreeNode = new TreeNode(1);
			
			var branch1:TreeNode = new TreeNode(2);
			var branch2:TreeNode = new TreeNode(5);
			var branch3:TreeNode = new TreeNode(8);
			
			tree1.appendChild(branch2);
			tree1.insertBefore(branch2, branch1);
			tree1.insertAfter(branch2, branch3);
			
			Assert.areEquals(branch1, tree1.firstChild);
			Assert.areEquals(branch3, tree1.lastChild);
			Assert.areEquals(branch2, tree1.firstChild.nextSibling);
			Assert.areEquals(branch2, tree1.lastChild.previousSibling);
			
			Assert.areEquals(0, tree1.getDepth());
			Assert.areEquals(1, branch1.getDepth());
			Assert.areEquals(tree1, branch2.getRoot());
			
			Assert.isTrue(tree1.hasChildren());
			
			Assert.isFalse(tree1.hasSiblings());
			Assert.isTrue(branch1.hasSiblings());
			Assert.isTrue(branch2.hasSiblings());
			Assert.isTrue(branch3.hasSiblings());
			
			var branch4:TreeNode = new TreeNode(3);
			var branch5:TreeNode = new TreeNode(4);
			
			branch1.appendChild(branch4);
			branch1.appendChild(branch5);
			
			Assert.areEquals(2, branch5.getDepth());
			Assert.areEquals(tree1, branch5.getRoot());
			Assert.areEquals(6, tree1.count);
			
			var branch6:TreeNode = new TreeNode(6);
			var branch7:TreeNode = new TreeNode(7);
			
			branch6.appendChild(branch7);
			branch2.appendChild(branch6);
			
			Assert.areEquals(2, branch6.getDepth());
			Assert.areEquals(3, branch7.getDepth());
			Assert.areEquals(tree1, branch7.getRoot());
			Assert.areEquals(8, tree1.count);
			
			var e:IEnumerator = tree1.getEnumerator();
			var txt:Array = new Array();
			
			while(e.moveNext()) {
				txt.push(e.current.value);
			}
			
			Assert.areEquals("1|2|3|4|5|6|7|8", txt.join("|"));
			
			e = branch1.getEnumerator();
			txt = new Array();
			
			while(e.moveNext()) {
				txt.push(e.current.value);
			}
			
			Assert.areEquals("2|3|4", txt.join("|"));
			
			e = branch4.getEnumerator();
			txt = new Array();
				
			while(e.moveNext()) {
				txt.push(e.current.value);
			}
			
			Assert.areEquals("3", txt.join("|"));
			
			var e2:IEnumerator = tree1.getPostOrderEnumerator();
			txt = new Array();
			
			while(e2.moveNext()) {
				txt.push(e2.current.value);
			}
			
			Assert.areEquals("3|4|2|7|6|5|8|1", txt.join("|"));
			
			e2 = branch1.getPostOrderEnumerator();
			txt = new Array();
			
			while(e2.moveNext()) {
				txt.push(e2.current.value);
			}
			
			Assert.areEquals("3|4|2", txt.join("|"));
			
			e2 = branch4.getPostOrderEnumerator();
			txt = new Array();
				
			while(e2.moveNext()) {
				txt.push(e2.current.value);
			}
			
			Assert.areEquals("3", txt.join("|"));
			
			
			e2 = branch2.getPostOrderEnumerator();
			txt = new Array();
				
			while(e2.moveNext()) {
				txt.push(e2.current.value);
			}
			
			Assert.areEquals("7|6|5", txt.join("|"));
			
			//Serialization
			var tr2:TreeNode = ObjectUtils.clone(tree1) as TreeNode;
			txt = new Array();
			
			e = tr2.getEnumerator();
			while(e.moveNext()) {
				txt.push(e.current.value);
			}
			
			Assert.areEquals("1|2|3|4|5|6|7|8", txt.join("|"));
			
			Assert.areEquals("1|2|3|4|5|6|7|8", tr2.toArray().join("|"));
		}

		private function testLinkedList():void {
			var ll1:List = new List(1, 2, 3); //ll1: 1, 2, 3

			Assert.areEquals(3, ll1.count);
			Assert.areEquals("1|2|3", ll1.toArray().join("|"));
			
			ll1.push(10);
			Assert.areEquals(4, ll1.count);
			Assert.areEquals("1|2|3|10", ll1.toArray().join("|"));
			
			ll1.unshift(11, 12);
			Assert.areEquals(6, ll1.count);
			Assert.areEquals("11|12|1|2|3|10", ll1.toArray().join("|"));
			
			Assert.isTrue(ll1.contains(3));
			Assert.isFalse(ll1.contains(9));
			
			Assert.areEquals(10, ll1.pop());
			Assert.areEquals(11, ll1.shift());
			
			ll1.unshift(2, -1);
			ll1.push(13, 14);
			
			var ll2:List = ObjectUtils.clone(ll1) as List;
			var txt:Array = new Array();
			
			var e:IEnumerator = ll2.getEnumerator();
			while(e.moveNext()) {
				txt.push(e.current);
			}
			
			Assert.areEquals("2|-1|12|1|2|3|13|14", txt.join("|"));
		}

		private function testDictionary():void {
			var dc:Dictionary = new Dictionary();
			
			dc.add("key1", 1);
			Assert.areEquals(1, dc.count);
			
			dc.add("key2", 2);
			Assert.areEquals(2, dc.count);
			
			dc.add("3", {val:3});
			Assert.areEquals(3, dc.count);
			
			Assert.areEquals(1, dc["key1"]);
			Assert.areEquals(2, dc["key2"]);
			Assert.areEquals(3, dc["3"].val);
			
			dc.add("key2", 4);
			Assert.areEquals(4, dc["key2"]);
			Assert.areEquals(3, dc.count);
			
			
			Assert.isTrue(dc.containsKey("key2"));
			Assert.isTrue(dc.containsValue(4));
			Assert.isFalse(dc.containsValue(2));
			
			dc.remove("key2");
			Assert.areEquals(2, dc.count);
			Assert.isFalse(dc.containsKey("key2"));
			Assert.isFalse(dc.containsValue(4));
			
			var txt1:Array = new Array();
			var txt2:Array = new Array();
			
			var e:IEnumerator = dc.getEnumerator();
			while(e.moveNext()) {
				txt1.push(e.current.key);
				txt2.push(e.current.value);
			}
			
			Assert.areEquals("key1|3", txt1.join("|"));
			Assert.areEquals("1|[object Object]", txt2.join("|"));
			
			var dc2:Dictionary = ObjectUtils.clone(dc) as Dictionary;
			
			Assert.areEquals(1, dc2["key1"]);
			Assert.areEquals(3, dc2["3"].val);
			
			dc2.add("key2", 4);
			Assert.areEquals(4, dc2["key2"]);
			Assert.areEquals(3, dc2.count);
			Assert.isFalse(dc.containsKey("key2"));
			
			delete dc2["key2"];
			Assert.areEquals(2, dc2.count);
			Assert.isFalse(dc2.containsKey("key2"));
			Assert.isFalse(dc2.containsValue(4));
		}

		private function testArrayList():void {
			var al:ArrayList = new ArrayList();
			al.add(3);
			Assert.areEquals(1, al.count);
			
			al.add(1);
			Assert.areEquals(2, al.count);
			
			al.add(2);
			Assert.areEquals(3, al.count);
			
			//3, 1, 2
			Assert.areEquals(3, al[0]);
			Assert.areEquals(1, al[1]);
			Assert.areEquals(2, al[2]);
			
			Assert.areEquals(al.indexOf(2), 2);
			Assert.isTrue(al.contains(1));
			Assert.isFalse(al.contains(5));
			
			var al2:ArrayList = new ArrayList(al);
			//3, 1, 2
			Assert.areEquals(3, al2[0]);
			Assert.areEquals(1, al2[1]);
			Assert.areEquals(2, al2[2]);
			
			al.insertRange(1, al2);
			//3, 3, 1, 2, 1, 2
			Assert.areEquals(6, al.count);
			
			Assert.areEquals(al[1], 3);
			Assert.areEquals(al[2], 1);
			Assert.areEquals(al[3], 2);
			
			al.remove(3);
			//3, 1, 2, 1, 2
			Assert.areEquals(5, al.count);
			Assert.areEquals(al[1], 1);
			
			al.insert(2, 4);
			al.insert(4, 9);
			al.sort();
			//1,1,2,2,3,4,9
			//1,1,2,2,3,4,[insertion point],9
			//~6 = -7
			Assert.areEquals(-7, al.binarySearch(6));
			Assert.areEquals(4, al.binarySearch(3));
			Assert.areEquals(-8, al.binarySearch(11));
			
			var txt:Array = new Array();

			var e:IEnumerator = al.getEnumerator();
			while(e.moveNext()) {
				txt.push(e.current);
			}
			
			Assert.areEquals("1|1|2|2|3|4|9", txt.join("|"));
			
			//Serialization
			var al3:ArrayList = ObjectUtils.clone(al) as ArrayList;
			
			Assert.areEquals(-7, al3.binarySearch(6));
			Assert.areEquals(4, al3.binarySearch(3));
			Assert.areEquals(-8, al3.binarySearch(11));
			Assert.areEquals(7, al3.count);
			
			//it's a clone, so it should not be equal...
			Assert.isFalse(al3.equals(al));
		}
		
		
		private function resizeStage(event:Event):void {
			_tf.width = stage.stageWidth;
			_tf.height = stage.stageHeight;
		}
	}
}
